from httpx import AsyncClient
from re import findall
from os.path import exists
from random import choice
from loguru import logger
import asyncio


def get_proxy():
    return choice(proxies)


async def _get_inbox_message(hash: str, eml: str):
    proxy = get_proxy()

    async with AsyncClient(proxies={
                "http://": proxy,
                "https://": proxy
            }) as client:
        url = ("https://api.mytemp.email/1/eml/get"
               f"?eml={eml}&hash={hash}&sid=9400042&task=163&tt=11209")
        response = await client.get(url)
        data = response.json()

    return findall(r"\d+", data["body_text"])[0]


async def get_message(email: str, hash: str):
    proxy = get_proxy()

    async with AsyncClient(proxies={
                "http://": proxy,
                "https://": proxy
            }) as client:
        url = ("https://api.mytemp.email/1/inbox/check"
               f"?inbox={email}&hash={hash}&sid=9400042&task=7&tt=36")
        response = await client.get(url)
        data = response.json()

    for message in data["emls"]:
        if message["from_address"] == "noreply@m.step.app":
            return await _get_inbox_message(message["hash"], message["eml"])

    await asyncio.sleep(1)
    return await get_message(email, hash)


async def get_email():
    proxy = get_proxy()

    async with AsyncClient(proxies={
                "http://": proxy,
                "https://": proxy
            }) as client:
        response = await client.post(
                "https://api.mytemp.email/1/inbox/create"
                "?sid=9400042"
                "&task=6&tt=35", json={
                    "sid": 9400042,
                    "task": 6,
                    "tt": 35
                })

        data = response.json()

    try:
        return data["inbox"], data["hash"]
    except KeyError:
        await asyncio.sleep(1)
        return await get_email()


async def register_account(r: str):
    logger.info("Регистрация акаунта")

    email, hash = await get_email()
    proxy = get_proxy()
    async with AsyncClient(cookies={"r": r}, proxies={
                "http://": proxy,
                "https://": proxy
            }) as client:
        response = await client.get("https://api.step.app/v1/auth/otp-code"
                                    f"?email={email}")
        data = response.text

        if "OK" not in data:
            raise Exception("Не удалось зарегистрировать аккаунт")

        code = await get_message(email, hash)
        response = await client.get("https://api.step.app/v1/auth/token"
                                    f"?email={email}"
                                    f"&code={code}")
        data = response.json()

        if "access" not in data:
            raise Exception("Не удалось зарегистрировать аккаунт")

    return email, data["access"]["token"], data["refresh"]["token"]


async def add_referrer(r: str, access_token: str):
    logger.info("Установка реферального кода")

    proxy = get_proxy()

    async with AsyncClient(
            headers={"Authorization": f"Bearer {access_token}"},
            proxies={
                "http://": proxy,
                "https://": proxy
            }) as client:
        response = await client.patch(
                url="https://api.step.app/v1/user/me",
                json={"referrer": r})
    return "OK" in response.text


async def worker(r: str):
    while True:
        logger.info("Попытка создать новый аккаунт")

        try:
            email, access_token, refresh_token = await register_account(r)

            if await add_referrer(r, access_token):
                logger.info("{} - Аккаунт успешно зарегистрирован", email)
            else:
                logger.info("{} - Не удалось установить реферальный код", email)
            await asyncio.sleep(1)
        except Exception:
            logger.exception("Ошибка при регистрации")


async def main():
    referrer = input("Реф код - ")
    tasks = [asyncio.create_task(worker(referrer))
             for _ in range(int(input("Кол-во потоков - ")))]

    await asyncio.gather(*tasks)


if exists("proxy.txt"):
    proxies = open("proxy.txt").read().strip().split("\n")
else:
    proxies = [None]

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

loop.run_until_complete(main())
